home *** CD-ROM | disk | FTP | other *** search
/ Suzy B Software 2 / Suzy B Software CD-ROM 2 (1994).iso / new_file / mintprgs / mint112s / mint112s.lzh / procfs.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-11-14  |  18.3 KB  |  772 lines

  1. /*
  2. Copyright 1991,1992 Eric R. Smith.
  3. Copyright 1992,1993,1994 Atari Corporation.
  4. All rights reserved.
  5.  */
  6.  
  7. /* PROC pseudo-filesystem routines */
  8. /* basically just to allow 'ls -l X:' to give a list of active processes
  9.  * some things to note:
  10.  * process names are given as name.XXX, where 'XXX' is the pid of the
  11.  *   process
  12.  * process attributes depend on the run queue as follows:
  13.  *   RUNNING:    0x00        (normal)
  14.  *   READY:    0x01        (read-only)
  15.  *   WAIT:    0x20        (archive bit)
  16.  *   IOBOUND:    0x21        (archive bit+read-only)
  17.  *   ZOMBIE:    0x22        (archive+hidden)
  18.  *   TSR:    0x02        (hidden)
  19.  *   STOP:    0x24        (archive bit+system)
  20.  * the general principle is: inactive processes have the archive bit (0x20)
  21.  * set, terminated processes have the hidden bit (0x02) set, stopped processes
  22.  * have the system bit (0x04) set, and the read-only bit is used to
  23.  * otherwise distinguish states (which is unfortunate, since it would be
  24.  * nice if this bit corresponded with file permissions).
  25.  */
  26.  
  27. #include "mint.h"
  28.  
  29.  
  30. static long    ARGS_ON_STACK proc_root    P_((int drv, fcookie *fc));
  31. static long    ARGS_ON_STACK proc_lookup    P_((fcookie *dir, const char *name, fcookie *fc));
  32. static long    ARGS_ON_STACK proc_getxattr    P_((fcookie *fc, XATTR *xattr));
  33. static long    ARGS_ON_STACK proc_chattr    P_((fcookie *fc, int attrib));
  34. static long    ARGS_ON_STACK proc_chown    P_((fcookie *fc, int uid, int gid));
  35. static long    ARGS_ON_STACK proc_chmode    P_((fcookie *fc, unsigned mode));
  36. static long    ARGS_ON_STACK proc_rmdir    P_((fcookie *dir, const char *name));
  37. static long    ARGS_ON_STACK proc_remove    P_((fcookie *dir, const char *name));
  38. static long    ARGS_ON_STACK proc_getname    P_((fcookie *root, fcookie *dir, char *pathname,
  39.                             int size));
  40. static long    ARGS_ON_STACK proc_rename    P_((fcookie *olddir, char *oldname,
  41.                     fcookie *newdir, const char *newname));
  42. static long    ARGS_ON_STACK proc_opendir    P_((DIR *dirh, int flags));
  43. static long    ARGS_ON_STACK proc_readdir    P_((DIR *dirh, char *nm, int nmlen, fcookie *));
  44. static long    ARGS_ON_STACK proc_rewinddir    P_((DIR *dirh));
  45. static long    ARGS_ON_STACK proc_closedir    P_((DIR *dirh));
  46. static long    ARGS_ON_STACK proc_pathconf    P_((fcookie *dir, int which));
  47. static long    ARGS_ON_STACK proc_dfree    P_((fcookie *dir, long *buf));
  48. static DEVDRV *    ARGS_ON_STACK proc_getdev    P_((fcookie *fc, long *devsp));
  49.  
  50. static long    ARGS_ON_STACK proc_open    P_((FILEPTR *f));
  51. static long    ARGS_ON_STACK proc_write    P_((FILEPTR *f, const char *buf, long bytes));
  52. static long    ARGS_ON_STACK proc_read    P_((FILEPTR *f, char *buf, long bytes));
  53. static long    ARGS_ON_STACK proc_lseek    P_((FILEPTR *f, long where, int whence));
  54. static long    ARGS_ON_STACK proc_ioctl    P_((FILEPTR *f, int mode, void *buf));
  55. static long    ARGS_ON_STACK proc_datime    P_((FILEPTR *f, short *time, int rwflag));
  56. static long    ARGS_ON_STACK proc_close    P_((FILEPTR *f, int pid));
  57. static long ARGS_ON_STACK proc_readlabel P_((fcookie *dir, char *name, int namelen));
  58.  
  59. /* dummy routines from biosfs.c */
  60. extern long    ARGS_ON_STACK null_select    P_((FILEPTR *f, long p, int mode));
  61. extern void    ARGS_ON_STACK null_unselect    P_((FILEPTR *f, long p, int mode));
  62.  
  63. static PROC *    name2proc    P_((const char *name));
  64.  
  65.  
  66. DEVDRV proc_device = {
  67.     proc_open, proc_write, proc_read, proc_lseek, proc_ioctl, proc_datime,
  68.     proc_close, null_select, null_unselect
  69. };
  70.  
  71. FILESYS proc_filesys = {
  72.     (FILESYS *)0,
  73.     0,
  74.     proc_root,
  75.     proc_lookup, nocreat, proc_getdev, proc_getxattr,
  76.     proc_chattr, proc_chown, proc_chmode,
  77.     nomkdir, proc_rmdir, proc_remove, proc_getname, proc_rename,
  78.     proc_opendir, proc_readdir, proc_rewinddir, proc_closedir,
  79.     proc_pathconf, proc_dfree,
  80.     nowritelabel, proc_readlabel, nosymlink, noreadlink, nohardlink,
  81.     nofscntl, nodskchng
  82. };
  83.  
  84. long ARGS_ON_STACK 
  85. proc_root(drv, fc)
  86.     int drv;
  87.     fcookie *fc;
  88. {
  89.     if (drv == PROCDRV) {
  90.         fc->fs = &proc_filesys;
  91.         fc->dev = drv;
  92.         fc->index = 0L;
  93.         return 0;
  94.     }
  95.     fc->fs = 0;
  96.     return EINTRN;
  97. }
  98.  
  99. static PROC *
  100. name2proc(name)
  101.     const char *name;
  102. {
  103.     const char *pstr;
  104.     char c;
  105.     int i;
  106.  
  107.     pstr = name;
  108.     while ( (c = *name++) != 0) {
  109.         if (c == '.')
  110.             pstr = name;
  111.     }
  112.     if (!isdigit(*pstr) && *pstr != '-')
  113.         return 0;
  114.     i = (int)atol(pstr);
  115.     if (i == -1)
  116.         return curproc;
  117.     else if (i == -2)
  118.         i = curproc->ppid;
  119.     return pid2proc(i);
  120. }
  121.  
  122. static long ARGS_ON_STACK 
  123. proc_lookup(dir, name, fc)
  124.     fcookie *dir;
  125.     const char *name;
  126.     fcookie *fc;
  127. {
  128.     PROC *p;
  129.  
  130.     if (dir->index != 0) {
  131.         DEBUG(("proc_lookup: bad directory"));
  132.         return EPTHNF;
  133.     }
  134.  
  135. /* special case: an empty name in a directory means that directory */
  136. /* so does "." */
  137.     if (!*name || (name[0] == '.' && name[1] == 0)) {
  138.         *fc = *dir;
  139.         return 0;
  140.     }
  141.  
  142. /* another special case: ".." could be a mount point */
  143.     if (!strcmp(name, "..")) {
  144.         *fc = *dir;
  145.         return EMOUNT;
  146.     }
  147.  
  148.     if (0 == (p = name2proc(name))) {
  149.         DEBUG(("proc_lookup: name not found"));
  150.         return EFILNF;
  151.     } else {
  152.         fc->index = (long)p;
  153.         fc->fs = &proc_filesys;
  154.         fc->dev = PROC_RDEV_BASE | p->pid;
  155.     }
  156.     return 0;
  157. }
  158.  
  159. static int p_attr[NUM_QUEUES] = {    /* attributes corresponding to queues */
  160.     0,            /* "RUNNING" */
  161.     0x01,            /* "READY" */
  162.     0x20,            /* "WAITING" */
  163.     0x21,            /* "IOBOUND" */
  164.     0x22,            /* "ZOMBIE" */
  165.     0x02,            /* "TSR" */
  166.     0x24,            /* "STOPPED" */
  167.     0x21            /* "SELECT" (same as IOBOUND) */
  168. };
  169.  
  170. static long ARGS_ON_STACK 
  171. proc_getxattr(fc, xattr)
  172.     fcookie *fc;
  173.     XATTR *xattr;
  174. {
  175.     PROC *p;
  176.     extern int proctime, procdate;    /* see dosmem.c */
  177.  
  178.     xattr->blksize = 1;
  179.     if (fc->index == 0) {
  180.         /* the root directory */
  181.         xattr->index = 0;
  182.         xattr->dev = xattr->rdev = PROCDRV;
  183.         xattr->nlink = 1;
  184.         xattr->uid = xattr->gid = 0;
  185.         xattr->size = xattr->nblocks = 0;
  186.         xattr->mtime = xattr->atime = xattr->ctime = proctime;
  187.         xattr->mdate = xattr->adate = xattr->cdate = procdate;
  188.         xattr->mode = S_IFDIR | DEFAULT_DIRMODE;
  189.         xattr->attr = FA_DIR;
  190.         return 0;
  191.     }
  192.  
  193.     p = (PROC *)fc->index;
  194.     xattr->index = p->pid;
  195.     xattr->dev = xattr->rdev = PROC_RDEV_BASE | p->pid;
  196.     xattr->nlink = 1;
  197.     xattr->uid = p->euid; xattr->gid = p->egid;
  198.     xattr->size = xattr->nblocks = memused(p);
  199.     xattr->mtime = xattr->ctime = xattr->atime = p->starttime;
  200.     xattr->mdate = xattr->cdate = xattr->adate = p->startdate;
  201.     xattr->mode = S_IFMEM | S_IRUSR | S_IWUSR;
  202.     xattr->attr = p_attr[p->wait_q];
  203.     return 0;
  204. }
  205.  
  206. static long ARGS_ON_STACK 
  207. proc_chattr(fc, attrib)
  208.     fcookie *fc;
  209.     int attrib;
  210. {
  211.     UNUSED(fc); UNUSED(attrib);
  212.  
  213.     return EACCDN;
  214. }
  215.  
  216. static long ARGS_ON_STACK 
  217. proc_chown(fc, uid, gid)
  218.     fcookie *fc;
  219.     int uid, gid;
  220. {
  221.     UNUSED(fc); UNUSED(uid); UNUSED(gid);
  222.     return EINVFN;
  223. }
  224.  
  225. static long ARGS_ON_STACK 
  226. proc_chmode(fc, mode)
  227.     fcookie *fc;
  228.     unsigned mode;
  229. {
  230.     UNUSED(fc); UNUSED(mode);
  231.     return EINVFN;
  232. }
  233.  
  234. static long ARGS_ON_STACK 
  235. proc_rmdir(dir, name)
  236.     fcookie *dir;
  237.     const char *name;
  238. {
  239.     UNUSED(dir); UNUSED(name);
  240.     return EPTHNF;
  241. }
  242.  
  243. static long ARGS_ON_STACK 
  244. proc_remove(dir, name)
  245.     fcookie *dir;
  246.     const char *name;
  247. {
  248.     PROC *p;
  249.  
  250.     if (dir->index != 0)
  251.         return EPTHNF;
  252.     p = name2proc(name);
  253.     if (!p)
  254.         return EFILNF;
  255.  
  256. /* this check is necessary because the Fdelete code checks for
  257.  * write permission on the directory, not on individual
  258.  * files
  259.  */
  260.     if (curproc->euid && curproc->ruid != p->ruid) {
  261.         DEBUG(("proc_remove: wrong user"));
  262.         return EACCDN;
  263.     }
  264.     post_sig(p, SIGTERM);
  265.     check_sigs();        /* it might have been us */
  266.     return 0;
  267. }
  268.  
  269. static long ARGS_ON_STACK 
  270. proc_getname(root, dir, pathname, size)
  271.     fcookie *root, *dir; char *pathname;
  272.     int size;
  273. {
  274.     PROC *p;
  275.     char buffer[20]; /* enough if proc names no longer than 8 chars */
  276.  
  277.     UNUSED(root);
  278.  
  279.     if (dir->index == 0)
  280.         *buffer = 0;
  281.     else {
  282.         p = (PROC *)dir->index;
  283.         ksprintf(buffer, "%s.03d", p->name, p->pid);
  284.     }
  285.     if (strlen(buffer) < size) {
  286.         strcpy(pathname, buffer);
  287.         return 0;
  288.     }
  289.     else
  290.         return ERANGE;
  291. }
  292.  
  293. static long ARGS_ON_STACK 
  294. proc_rename(olddir, oldname, newdir, newname)
  295.     fcookie *olddir;
  296.     char *oldname;
  297.     fcookie *newdir;
  298.     const char *newname;
  299. {
  300.     PROC *p;
  301.     int i;
  302.  
  303.     if (olddir->index != 0 || newdir->index != 0)
  304.         return EPTHNF;
  305.     if ((p = name2proc(oldname)) == 0)
  306.         return EFILNF;
  307.  
  308.     oldname = p->name;
  309.     for (i = 0; i < PNAMSIZ; i++) {
  310.         if (*newname == 0 || *newname == '.') {
  311.             *oldname = 0; break;
  312.         }
  313.         *oldname++ = *newname++;
  314.     }
  315.     return 0;
  316. }
  317.  
  318. static long ARGS_ON_STACK 
  319. proc_opendir(dirh, flags)
  320.     DIR *dirh;
  321.     int flags;
  322. {
  323.     UNUSED(flags);
  324.  
  325.     dirh->index = 0;
  326.     return 0;
  327. }
  328.  
  329. static long ARGS_ON_STACK 
  330. proc_readdir(dirh, name, namelen, fc)
  331.     DIR *dirh;
  332.     char *name;
  333.     int namelen;
  334.     fcookie *fc;
  335. {
  336.     int i;
  337.     int giveindex = (dirh->flags == 0);
  338.     PROC *p;
  339.  
  340.     do {
  341.         i = dirh->index++;
  342. /* BUG: we shouldn't have the magic number "1000" for maximum proc pid */
  343.         if (i >= 1000) {
  344.             p = 0;
  345.             break;
  346.         }
  347.         p = pid2proc(i);
  348.     } while (!p);
  349.  
  350.     if (!p)
  351.         return ENMFIL;
  352.  
  353.     fc->index = (long)p;
  354.     fc->fs = &proc_filesys;
  355.     fc->dev = PROC_RDEV_BASE | p->pid;
  356.  
  357.     if (giveindex) {
  358.         namelen -= (int)sizeof(long);
  359.         if (namelen <= 0) return ERANGE;
  360.         *((long *)name) = (long)p->pid;
  361.         name += sizeof(long);
  362.     }
  363.     if (namelen < strlen(p->name) + 5)
  364.         return ENAMETOOLONG;
  365.  
  366.     ksprintf(name, "%s.%03d", p->name, p->pid);
  367.     return 0;
  368. }
  369.  
  370. static long ARGS_ON_STACK 
  371. proc_rewinddir(dirh)
  372.     DIR *dirh;
  373. {
  374.     dirh->index = 0;
  375.     return 0;
  376. }
  377.  
  378. static long ARGS_ON_STACK 
  379. proc_closedir(dirh)
  380.     DIR *dirh;
  381. {
  382.     UNUSED(dirh);
  383.     return 0;
  384. }
  385. static long ARGS_ON_STACK 
  386. proc_pathconf(dir, which)
  387.     fcookie *dir;
  388.     int which;
  389. {
  390.     UNUSED(dir);
  391.  
  392.     switch(which) {
  393.     case -1:
  394.         return DP_MAXREQ;
  395.     case DP_IOPEN:
  396.         return UNLIMITED;    /* no internal limit on open files */
  397.     case DP_MAXLINKS:
  398.         return 1;        /* we don't have hard links */
  399.     case DP_PATHMAX:
  400.         return PATH_MAX;    /* max. path length */
  401.     case DP_NAMEMAX:
  402.         return PNAMSIZ + 4;    /* max. length of individual name */
  403.                     /* the "+4" is for the pid: ".123" */
  404.     case DP_ATOMIC:
  405.         return UNLIMITED;    /* all writes are atomic */
  406.     case DP_TRUNC:
  407.         return DP_DOSTRUNC;    /* file names are truncated to 8.3 */
  408.     case DP_CASE:
  409.         return DP_CASEINSENS;    /* case preserved, but ignored */
  410.     case DP_MODEATTR:
  411.         return (0777L << 8)|
  412.                 DP_FT_DIR|DP_FT_MEM;
  413.     case DP_XATTRFIELDS:
  414.         return DP_INDEX|DP_DEV|DP_NLINK|DP_UID|DP_GID|DP_BLKSIZE|DP_SIZE|
  415.                 DP_NBLOCKS;
  416.     default:
  417.         return EINVFN;
  418.     }
  419. }
  420.  
  421. static long ARGS_ON_STACK 
  422. proc_dfree(dir, buf)
  423.     fcookie *dir;
  424.     long *buf;
  425. {
  426.     long size;
  427. /* "sector" size is the size of the smallest amount of memory that can be
  428.    allocated. see mem.h for the definition of ROUND
  429.  */
  430.     long secsiz = ROUND(1);
  431.  
  432.     UNUSED(dir);
  433.  
  434.     size = tot_rsize(core, 0) + tot_rsize(alt, 0);
  435.     *buf++ = size/secsiz;            /* number of free clusters */
  436.     size = tot_rsize(core, 1) + tot_rsize(alt, 1);
  437.     *buf++ = size/secsiz;            /* total number of clusters */
  438.     *buf++ = secsiz;            /* sector size (bytes) */
  439.     *buf = 1;                /* cluster size (in sectors) */
  440.     return 0;
  441. }
  442.  
  443. static DEVDRV * ARGS_ON_STACK 
  444. proc_getdev(fc, devsp)
  445.     fcookie *fc;
  446.     long *devsp;
  447. {
  448.     PROC *p;
  449.  
  450.     p = (PROC *)fc->index;
  451.  
  452.     *devsp = (long)p;
  453.     return &proc_device;
  454. }
  455.  
  456. /*
  457.  * PROC device driver
  458.  */
  459.  
  460. /*
  461.  * BUG: file locking and the O_SHMODE restrictions are not implemented
  462.  * for processes
  463.  */
  464.  
  465. static long ARGS_ON_STACK 
  466. proc_open(f)
  467.     FILEPTR *f;
  468. {
  469.     UNUSED(f);
  470.  
  471.     return 0;
  472. }
  473.  
  474. static long ARGS_ON_STACK 
  475. proc_write(f, buf, nbytes)
  476.     FILEPTR *f; const char *buf; long nbytes;
  477. {
  478.     PROC *p = (PROC *)f->devinfo;
  479.     char *where;
  480.     long bytes_written = 0;
  481.     int prot_hold;
  482.  
  483.     where = (char *)f->pos;
  484.  
  485. TRACE(("proc_write to pid %d: %ld bytes to %lx", p->pid, nbytes, where));
  486.  
  487.     prot_hold = mem_access_for(p, (ulong)where,nbytes);
  488.     if (prot_hold == 0) {
  489.         DEBUG(("Can't Fwrite that memory: not all the same or not owner."));
  490.         return EACCDN;
  491.     }
  492.     if (prot_hold == 1) {
  493.         DEBUG(("Attempt to Fwrite memory crossing a managed boundary"));
  494.         return EACCDN;
  495.     }
  496.  
  497.     bytes_written = nbytes;
  498.     while (nbytes-- > 0) {
  499.         *where++ = *buf++;
  500.     }
  501.     cpush((void *)f->pos, bytes_written);    /* flush cached data */
  502.  
  503.     /* MEMPROT: done with temp mapping (only call if temp'ed above) */
  504.     if (prot_hold != -1) prot_temp((ulong)f->pos,bytes_written,prot_hold);
  505.  
  506.     f->pos += bytes_written;
  507.     return bytes_written;
  508. }
  509.  
  510. static long ARGS_ON_STACK 
  511. proc_read(f, buf, nbytes)
  512.     FILEPTR *f; char *buf; long nbytes;
  513. {
  514.     PROC *p = (PROC *)f->devinfo;
  515.     char *where;
  516.     long bytes_read = 0;
  517.     int prot_hold;
  518.  
  519.     where = (char *)f->pos;
  520.  
  521. TRACE(("proc_read from pid %d: %ld bytes from %lx", p->pid, nbytes, where));
  522.  
  523.     prot_hold = mem_access_for(p, (ulong)where,nbytes);
  524.     if (prot_hold == 0) {
  525.         DEBUG(("Can't Fread that memory: not all the same."));
  526.         return EACCDN;
  527.     }
  528.     if (prot_hold == 1) {
  529.         DEBUG(("Attempt to Fread memory crossing a managed boundary"));
  530.         return EACCDN;
  531.     }
  532.  
  533.     bytes_read = nbytes;
  534.     while (nbytes-- > 0) {
  535.         *buf++ = *where++;
  536.     }
  537.  
  538.     /* MEMPROT: done with temp mapping (only call if temp'ed above) */
  539.     if (prot_hold != -1) prot_temp((ulong)f->pos,bytes_read,prot_hold);
  540.  
  541.     f->pos += bytes_read;
  542.     return bytes_read;
  543. }
  544.  
  545. /*
  546.  * proc_ioctl: currently, the only IOCTL's available are:
  547.  * PPROCADDR: get address of PROC structure's "interesting" bits
  548.  * PCTXTSIZE: get the size of the CONTEXT structure
  549.  * PBASEADDR: get address of process basepage
  550.  * PSETFLAGS: set the memory allocation flags (e.g. to malloc from fastram)
  551.  * PGETFLAGS: get the memory allocation flags
  552.  * PTRACESFLAGS: set the process tracing flags
  553.  * PTRACEGFLAGS: get the process tracing flags
  554.  * PTRACEGO: restart the process (T1=0/T1=0)
  555.  * PTRACEFLOW: restart the process (T1=0/T0=1)
  556.  * PTRACESTEP: restart the process (T1=1/T0=0)
  557.  * PTRACE11: restart the process (T1=1/T0=1)
  558.  * PLOADINFO: get information about the process name and command line
  559.  */
  560.  
  561. static long ARGS_ON_STACK 
  562. proc_ioctl(f, mode, buf)
  563.     FILEPTR *f; int mode; void *buf;
  564. {
  565.     PROC *p;
  566.     extern long mcpu;    /* in main.c */
  567.     short sr;
  568.  
  569.     p = (PROC *)f->devinfo;
  570.     switch(mode) {
  571.     case PPROCADDR:
  572.         *((long *)buf) = (long)&p->magic;
  573.         return 0;
  574.     case PBASEADDR:
  575.         if (p == rootproc)
  576.             *((long *)buf) = (long)_base;
  577.         else
  578.             *((long *)buf) = (long)p->base;
  579.         return 0;
  580.     case PCTXTSIZE:
  581.         *((long *)buf) = sizeof(CONTEXT);
  582.         return 0;
  583.     case PFSTAT:
  584.         {
  585.         FILEPTR *pf;
  586.         int pfd = (*(ushort *)buf);
  587.         if (pfd < MIN_HANDLE || pfd >= MAX_OPEN ||
  588.             (pf = p->handle[pfd]) == 0)
  589.             return EIHNDL;
  590.         return (*pf->fc.fs->getxattr)(&pf->fc, (XATTR *)buf);
  591.         }
  592.     case PSETFLAGS:
  593.         {
  594.         int newflags = (ushort)(*(long *)buf);
  595.         if ((newflags & F_OS_SPECIAL) &&
  596.             (!(p->memflags & F_OS_SPECIAL))) {
  597.             /* you're making the process OS_SPECIAL */
  598.             TRACE(("Fcntl OS_SPECIAL pid %d",p->pid));
  599.             p->memflags = newflags;
  600.             mem_prot_special(p);
  601.         }
  602.         /* note: only the low 16 bits are actually used */
  603.         p->memflags = *((long *)buf);
  604.         return 0;
  605.         }
  606.     case PGETFLAGS:
  607.         *((long *)buf) = p->memflags;
  608.         return 0;
  609.     case PTRACESFLAGS:
  610.         if (p->ptracer == curproc || p->ptracer == 0) {
  611.             p->ptraceflags = *(ushort *)buf;
  612.             if (p->ptraceflags == 0) {
  613.                 p->ptracer = 0;
  614.                 p->ctxt[CURRENT].ptrace = 0;
  615.                 p->ctxt[SYSCALL].ptrace = 0;
  616.         /* if the process is stopped, restart it */
  617.                 if (p->wait_q == STOP_Q) {
  618.                     p->sigpending &= ~STOPSIGS;
  619.                     post_sig(p, SIGCONT);
  620.                 }
  621.             } else if (p == curproc) {
  622.                 p->ptracer = pid2proc(p->ppid);
  623.             } else {
  624.                 p->ptracer = curproc;
  625.             }
  626.         } else {
  627.             DEBUG(("proc_ioctl: process already being traced"));
  628.             return EACCDN;
  629.         }
  630.         return 0;
  631.     case PTRACEGFLAGS:
  632.         if (p->ptracer == curproc) {
  633.             *(ushort *)buf = p->ptraceflags;
  634.             return 0;
  635.         } else {
  636.             return EACCDN;
  637.         }
  638.     case PTRACE11:
  639.         return EINVFN;
  640.     case PTRACEFLOW:
  641.         if (mcpu < 20) {
  642.             DEBUG(("proc_ioctl: wrong processor"));
  643.             return EINVFN;
  644.         }
  645.         /* fall through */
  646.     case PTRACEGO:
  647.     case PTRACESTEP:
  648.         if (!p->ptracer) {
  649.             DEBUG(("proc_ioctl(PTRACE): process not being traced"));
  650.             return EACCDN;
  651.         }
  652.         else if (p->wait_q != STOP_Q) {
  653.             DEBUG(("proc_ioctl(PTRACE): process not stopped"));
  654.             return EACCDN;
  655.         }
  656.         else if (p->wait_cond &&
  657.             (1L << ((p->wait_cond >> 8) & 0x1f)) & STOPSIGS) {
  658.             DEBUG(("proc_ioctl(PTRACE): process stopped by job control"));
  659.             return EACCDN;
  660.         }
  661.         if (buf && *(ushort *)buf >= NSIG) {
  662.             DEBUG(("proc_ioctl(PTRACE): illegal signal number"));
  663.             return ERANGE;
  664.         }
  665.         p->ctxt[SYSCALL].sr &= 0x3fff;    /* clear both trace bits */
  666.         p->ctxt[SYSCALL].sr |= (mode - PTRACEGO) << 14;
  667.         /* Discard the saved frame */
  668.         p->ctxt[SYSCALL].sfmt = 0;
  669.         p->sigpending = 0;
  670.         if (buf && *(ushort *)buf != 0) {
  671. TRACE(("PTRACEGO: sending signal %d to pid %d", *(ushort *)buf, p->pid));
  672.             post_sig(p, *(ushort *)buf);
  673.  
  674. /* another SIGNULL hack... within check_sigs() we watch for a pending
  675.  * SIGNULL, if we see this then we allow delivery of a signal to the
  676.  * process, rather than telling the parent.
  677.  */
  678.             p->sigpending |= 1L;
  679.         } else {
  680. TRACE(("PTRACEGO: no signal"));
  681.         }
  682. /* wake the process up */
  683.         sr = spl7();
  684.         rm_q(p->wait_q, p);
  685.         add_q(READY_Q, p);
  686.         spl(sr);
  687.         return 0;
  688.     /* jr: PLOADINFO returns information about params passed to Pexec */
  689.     case PLOADINFO:
  690.         {
  691.             struct ploadinfo *pl = buf;
  692.  
  693.             if (!p->fname[0]) return EFILNF;
  694.             strncpy (pl->cmdlin, p->cmdlin, 128);
  695.             if (strlen (p->fname) <= pl->fnamelen)
  696.                 strcpy (pl->fname, p->fname);
  697.             else
  698.                 return ENAMETOOLONG;
  699.         }
  700.         return 0;
  701.  
  702.     case FIONREAD:
  703.     case FIONWRITE:
  704.         *((long *)buf) = 1L;    /* we're always ready for i/o */
  705.         return 0;
  706.     case FIOEXCEPT:
  707.         *((long *)buf) = 0L;
  708.         return 0;
  709.     default:
  710.         DEBUG(("procfs: bad Fcntl command"));
  711.     }
  712.     return EINVFN;
  713. }
  714.  
  715. static long ARGS_ON_STACK 
  716. proc_lseek(f, where, whence)
  717.     FILEPTR *f; long where; int whence;
  718. {
  719.     switch(whence) {
  720.     case 0:
  721.     case 2:
  722.         f->pos = where;
  723.         break;
  724.     case 1:
  725.         f->pos += where;
  726.         break;
  727.     default:
  728.         return EINVFN;
  729.     }
  730.     return f->pos;
  731. }
  732.  
  733. static long ARGS_ON_STACK 
  734. proc_datime(f, timeptr, rwflag)
  735.     FILEPTR *f;
  736.     short *timeptr;
  737.     int rwflag;
  738. {
  739.     PROC *p;
  740.  
  741.     p = (PROC *)f->devinfo;
  742.     if (rwflag) {
  743.         return EACCDN;
  744.     }
  745.     else {
  746.         *timeptr++ = p->starttime;
  747.         *timeptr = p->startdate;
  748.     }
  749.     return 0;
  750. }
  751.  
  752. static long ARGS_ON_STACK 
  753. proc_close(f, pid)
  754.     FILEPTR *f;
  755.     int pid;
  756. {
  757.     UNUSED(f); UNUSED(pid);
  758.     return 0;
  759. }
  760.  
  761. static long ARGS_ON_STACK 
  762. proc_readlabel(dir, name, namelen)
  763.     fcookie *dir;
  764.     char *name;
  765.     int namelen;
  766. {
  767.     UNUSED(dir);
  768.  
  769.     strncpy(name, "Processes", namelen-1);
  770.     return (strlen("Processes") < namelen) ? 0 : ENAMETOOLONG;
  771. }
  772.